import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 设置中文字体
plt.rcParams["font.sans-serif"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False  # 确保负号正确显示

# 读取数据并处理
try:
    df = pd.read_csv('boston.csv')
except FileNotFoundError:
    print("错误：找不到'boston.csv'文件，请确保文件路径正确。")
    exit()

# 数据预处理
df['AGE_adj'] = 100 - df['AGE']  # 转换为1940年后建成比例

# 创建年龄区间（每10%一个区间）
bins = np.arange(0, 101, 10)
df['AGE_bin'] = pd.cut(df['AGE_adj'], bins=bins, labels=[f"{i}-{i + 10}%" for i in range(0, 100, 10)])

# 计算各区间的统计量
grouped = df.groupby('AGE_bin', observed=False)['MEDV'].agg(['mean', 'std', 'count'])

# 计算95%置信区间
z_score = 1.96  # 标准正态分布的95%分位数
grouped['ci_low'] = grouped['mean'] - z_score * grouped['std'] / np.sqrt(grouped['count'])
grouped['ci_high'] = grouped['mean'] + z_score * grouped['std'] / np.sqrt(grouped['count'])

# 准备绘图
plt.figure(figsize=(10, 6))
plt.style.use('ggplot')   # 使用seaborn风格的网格

# 绘制均值趋势线
plt.plot(grouped.index, grouped['mean'], marker='o', color='#3B6CB2', linewidth=2.5, label='均值趋势')

# 绘制置信区间区域
plt.fill_between(grouped.index, grouped['ci_low'], grouped['ci_high'], color='#A9D0F5', alpha=0.3)

# 标注AGE>90%的异常点
mask = grouped.index.str.startswith('90')
if any(mask):
    plt.scatter(grouped.index[mask], grouped['mean'][mask], color='red', s=120,
                edgecolors='black', linewidth=1, label='AGE>90%区域')

    # 添加异常点标注
    for idx, value in zip(grouped.index[mask], grouped['mean'][mask]):
        plt.annotate(f'{value:.1f}千美元',
                     xy=(idx, value),
                     xytext=(0, 10),
                     textcoords='offset points',
                     ha='center',
                     bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="gray", alpha=0.8))

# 美化图表
plt.title('房价随房龄变化趋势（1940年后建造比例）', fontsize=15, pad=15)
plt.xlabel('1940年后建成比例', fontsize=12, labelpad=10)
plt.ylabel('房价中位数（千美元）', fontsize=12, labelpad=10)

# 设置坐标轴
plt.xticks(rotation=45, ha='right', fontsize=10)
plt.ylim(bottom=0)  # 确保Y轴从0开始

# 优化网格和图例
plt.grid(True, linestyle='--', alpha=0.6, color='gray')
plt.legend(loc='upper left', frameon=True, framealpha=0.9)

# 微调布局
plt.tight_layout()
plt.show()

# 打印关键统计数据
print("\n各房龄区间房价统计：")
print(grouped[['mean', 'std', 'count', 'ci_low', 'ci_high']].rename(
    columns={'mean': '平均房价', 'std': '标准差', 'count': '样本数',
             'ci_low': '95%置信下限', 'ci_high': '95%置信上限'}).round(2))